#include "moduleelectronicscaleshimadzu.h"
#include "moduleelectronicscaledefine.h"
#include "moduleelectronicscaleparamid.h"
#include "moduleelectronicscaleconfigid.h"
#include "moduleelectronicscalecmdid.h"
#include "moduleelectronicscaleeventid.h"
#include "electronicscaletool.h"
#include <QVariant>
#include <QDateTime>
#include <QDebug>

#define USED_TEST_TIMER 0

ModuleElectronicScaleShimadzu::ModuleElectronicScaleShimadzu(QObject *parent)
    : BaseModuleWithPort(parent)
{
    m_recorder = new ElectronicScaleRecorder(this);
    m_intervalRate = new ElectronicScaleIntervalRate(this);

    m_timer = new QTimer();
    m_timer->setInterval(1000);
    connect(m_timer, &QTimer::timeout, this, &ModuleElectronicScaleShimadzu::onTimeout);

    m_testTimer = new QTimer();
    m_testTimer->setInterval(1000);
    connect(m_testTimer, &QTimer::timeout, this, &ModuleElectronicScaleShimadzu::onTestTimeout);
}

ModuleElectronicScaleShimadzu::~ModuleElectronicScaleShimadzu()
{
    delete m_testTimer;
    delete m_timer;
    delete m_intervalRate;
    delete m_recorder;
}

electronicscale::ElectronicScaleParam &ModuleElectronicScaleShimadzu::param()
{
    QMutexLocker locker(m_mutex);
    return m_param;
}

bool ModuleElectronicScaleShimadzu::setConfig(int id, QVariant &var)
{
    QMutexLocker locker(m_mutex);
    bool ret = false;
    switch (id)
    {
        case ModuleElectronicScaleConfigID_ClearAllWeightData:
            m_param.samples.clear();
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_ShowAllWeightData:
            foreach (auto sample, m_param.samples)
            {
                QVariant var;
                var.setValue(sample);
                onParseCompleted(electronicscale::ElectronicScaleCmdID_Weight, var);
            }
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_ExportWeightDataToXlsx:
            {
                QString path = var.toString();
                ret = ElectronicScaleTool::exportWeightDataToXlsx(path, m_param.samples);
            }
            break;
        case ModuleElectronicScaleConfigID_ImportWeightDataFromXlsx:
            {
                m_param.samples.clear();
                QString path = var.toString();
                ret = ElectronicScaleTool::importWeightDataFromXlsx(path, m_param.samples);
            }
            break;
        case ModuleElectronicScaleConfigID_RecordFileName:
            m_recorder->setFileName(var.toString());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_RecordPeriod:
            m_recorder->setPeriod(var.toUInt());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_StartRecord:
            ret = m_recorder->start();
            if (ret)
            {
                m_param.samples.clear();

                m_intervalRate->start();

                QTimer::singleShot(0, this, [=](){
//                    m_timer->start(); // 收到第一个数据才启动定时器
#if USED_TEST_TIMER
                    m_testTimer->start();
#endif
                });
            }
            break;
        case ModuleElectronicScaleConfigID_StopRecord:
            {
                ret = m_recorder->stop();
                m_intervalRate->stop();
                electronicscale::IntervalRate rate = m_intervalRate->stopToCalculate();

                QVariant var;
                var.setValue(rate);
                emit moduleEvent(ModuleElectronicScaleEventID_ShowIntervalRate, var);

                QTimer::singleShot(0, this, [=](){
                    m_timer->stop();
                    m_testTimer->stop();
                });
            }
            break;
        case ModuleElectronicScaleConfigID_Interval:
            m_intervalRate->setInterval(var.toUInt());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_CalculateIntervalRates:
            {
                if (!m_intervalRate->isStart())
                {
                    QList<electronicscale::IntervalRate> rates;
                    rates = ElectronicScaleIntervalRate::calculate(m_param.samples, m_intervalRate->getInterval());
//                    var.setValue(rates);
                    m_intervalRate->setIntervalRates(rates);
                    ret = true;
                }
            }
            break;
        case ModuleElectronicScaleConfigID_ShowIntervalRates:
            {
                QList<electronicscale::IntervalRate> rates;
                rates = m_intervalRate->getIntervalRates();
//                var.setValue(rates);
                foreach (auto r, rates)
                {
                    QVariant var;
                    var.setValue(r);
                    emit moduleEvent(ModuleElectronicScaleEventID_ShowIntervalRates, var);
                    qDebug() << r.time << r.rate.value << ElectronicScaleTool::toString(r.rate.unit);
                }
                ret = true;
            }
            break;
        case ModuleElectronicScaleConfigID_ExportIntervalRateDataToXlsx:
            {
                QString path = var.toString();
                ret = m_intervalRate->exportIntervalRateToXlsx(path);
            }
            break;
        case ModuleElectronicScaleConfigID_ImportIntervalRateDataFromXlsx:
            {
                QString path = var.toString();
                ret = m_intervalRate->importIntervalRateFromXlsx(path);
            }
            break;
        default:
            break;
    }
    return ret;
}

bool ModuleElectronicScaleShimadzu::getConfig(int id, QVariant &var)
{
    QMutexLocker locker(m_mutex);
    bool ret = false;
    switch (id)
    {

        case ModuleElectronicScaleConfigID_RecordFileName:
            var.setValue(m_recorder->getFileName());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_RecordPeriod:
            var.setValue(m_recorder->getPeriod());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_StartRecord:
            var.setValue(m_recorder->isRecording());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_Interval:
            var.setValue(m_intervalRate->getInterval());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_IntervalRate:
            var.setValue(m_intervalRate->getIntervalRate());
            ret = true;
            break;
        case ModuleElectronicScaleConfigID_IntervalRates:
            var.setValue(m_intervalRate->getIntervalRates());
            ret = true;
            break;

        default:
            break;
    }
    return ret;
}

bool ModuleElectronicScaleShimadzu::setParam(int id, QVariant &var)
{
    QMutexLocker locker(m_mutex);
    switch (id)
    {
        case ModuleElectronicScaleParamID_WeightBuffer:
            {
                QList<electronicscale::Sample> list = var.value<QList<electronicscale::Sample>>();
                m_param.samples = list;
            }
            break;
        default:
            break;
    }
    return true;
}

bool ModuleElectronicScaleShimadzu::getParam(int id, QVariant &var)
{
    QMutexLocker locker(m_mutex);
    switch (id)
    {
        case ModuleElectronicScaleParamID_WeightBuffer:
            var.setValue(m_param.samples);
            break;
        case ModuleElectronicScaleParamID_Weight:
            {
                electronicscale::Sample sample;
                QDateTime t = var.value<QDateTime>();
                qint64 time = t.toMSecsSinceEpoch();
                sample = ElectronicScaleTool::findWeight(time, m_param.samples);
                var.setValue(sample);
            }
            break;
        default:
            break;
    }
    return true;
}

void ModuleElectronicScaleShimadzu::onStart()
{
    QMutexLocker locker(m_mutex);
//    if (m_enable && m_port->isOpen())
    //        m_timer->start();
}

void ModuleElectronicScaleShimadzu::onParseCompleted(int id, const QVariant &data)
{
    emit parseCompleted(id, data);

    QMutexLocker locker(m_mutex);
    switch (id)
    {
        case electronicscale::ElectronicScaleCmdID_Weight:
        {
            electronicscale::Sample sample = data.value<electronicscale::Sample>();

            if (m_recorder->isRecording())
            {
                if (!m_timer->isActive()) // 从点击启动到收到第一个重量数据才是真正开始
                    m_timer->start();

                m_recorder->saveOneRecord(sample);
            }

            if (m_intervalRate->isStart())
            {
                m_intervalRate->addSample(sample);
                if (m_intervalRate->isCalculate())
                {
                    electronicscale::IntervalRate rate = m_intervalRate->calculate();

                    QVariant var;
                    var.setValue(rate);
                    emit moduleEvent(ModuleElectronicScaleEventID_ShowIntervalRate, var);
                }
            }

            if (m_param.samples.size() >= 10 * 3600)
                m_param.samples.clear();
            m_param.samples << sample;
        }
        break;
        default:
        break;
    }
}

void ModuleElectronicScaleShimadzu::onTimeout()
{
    QMutexLocker locker(m_mutex);
    m_recorder->onTimeout();
    m_intervalRate->onTimeout();

    // 时间到停止记录
    if (!m_recorder->isRecording())
    {
        m_timer->stop();

        m_recorder->stop();
        m_intervalRate->stop();
        electronicscale::IntervalRate rate = m_intervalRate->stopToCalculate();

        QVariant var;
        var.setValue(rate);
        emit moduleEvent(ModuleElectronicScaleEventID_ShowIntervalRate, var);
    }
}

void ModuleElectronicScaleShimadzu::onTestTimeout()
{
    electronicscale::Sample sample;
    sample.time = QDateTime::currentMSecsSinceEpoch();
    sample.weight.unit = electronicscale::WeightUnit::WeightUnit_g;
    qsrand(sample.time);
    sample.weight.value = qrand();
//    qDebug() << sample.weight.value;

    QVariant var;
    var.setValue(sample);
    onParseCompleted(electronicscale::ElectronicScaleCmdID_Weight, var);
}
